home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / mawk10.zip / SPLIT.C < prev    next >
C/C++ Source or Header  |  1991-10-05  |  4KB  |  195 lines

  1.  
  2. /********************************************
  3. split.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13. /* $Log:    split.c,v $
  14.  * Revision 3.5.1.1  91/09/14  17:24:21  brennan
  15.  * VERSION 1.0
  16.  * 
  17.  * Revision 3.5  91/08/13  06:52:12  brennan
  18.  * VERSION .9994
  19.  * 
  20.  * Revision 3.4  91/07/17  15:11:37  brennan
  21.  * pass length of s to space_split
  22.  * 
  23.  * Revision 3.3  91/06/28  04:17:40  brennan
  24.  * VERSION 0.999
  25.  * 
  26.  * Revision 3.2  91/06/10  15:59:39  brennan
  27.  * changes for V7
  28.  * 
  29.  * Revision 3.1  91/06/07  10:28:23  brennan
  30.  * VERSION 0.995
  31.  * 
  32.  * Revision 2.4  91/06/04  06:48:08  brennan
  33.  * removed <string.h>
  34.  * 
  35.  * Revision 2.3  91/05/28  09:05:18  brennan
  36.  * removed main_buff
  37.  * 
  38.  * Revision 2.2  91/05/15  12:07:41  brennan
  39.  * dval hash table for arrays
  40.  * 
  41.  * Revision 2.1  91/04/08  08:24:11  brennan
  42.  * VERSION 0.97
  43.  * 
  44. */
  45.  
  46. /* split.c */
  47.  
  48. #include "mawk.h"
  49. #include "symtype.h"
  50. #include "bi_vars.h"
  51. #include "bi_funct.h"
  52. #include "memory.h"
  53. #include "scan.h"
  54. #include "regexp.h"
  55. #include "field.h"
  56.  
  57.  
  58. /* split string s of length slen on SPACE without changing s.
  59.    load the pieces into STRINGS and ptrs into
  60.    temp_buff.ptr_buff[] 
  61.    return the number of pieces */
  62.  
  63. int space_split( s , slen)  
  64.   register char *s ;
  65.   unsigned slen ;
  66. { char *back = s + slen ;
  67.   int i = 0 ;
  68.   int len ;
  69.   char *q ;
  70.   STRING  *sval ;
  71.  
  72.   while ( 1 )
  73.   { while ( scan_code[*(unsigned char*)s] == SC_SPACE )  s++ ;
  74.     if ( *s == 0 )  break ;
  75.     /* mark the front with q */
  76.     q = s++ ;
  77.     *back = ' ' ; /* sentinal */
  78.     while ( scan_code[*(unsigned char*)s] != SC_SPACE )  s++ ;
  79.     *back = 0 ;
  80.     sval = (STRING *) (temp_buff.ptr_buff[i++] = 
  81.          (PTR) new_STRING((char *) 0, len = s - q )) ;
  82.     (void) memcpy(sval->str, q, SIZE_T(len)) ;
  83.   }
  84.  
  85.   return i ;
  86. }
  87.  
  88.  
  89. char *re_pos_match(s, re, lenp)
  90.   register char *s ; 
  91.   PTR re ; unsigned *lenp ;
  92. {
  93.   while ( s = REmatch(s, re, lenp) )
  94.         if ( *lenp )   return s ;
  95.         else
  96.         if ( *s == 0 )  break ;
  97.         else s++ ;
  98.  
  99.   return (char *) 0 ;
  100. }
  101.  
  102. int re_split(s, re)
  103.   char *s ;
  104.   PTR  re ;
  105. { register char *t ;
  106.   int i = 0 ;
  107.   unsigned mlen, len ;
  108.   STRING *sval ;
  109.  
  110.   while ( t = re_pos_match(s, re, &mlen) )
  111.   { sval = (STRING*)(temp_buff.ptr_buff[i++] = (PTR)
  112.             new_STRING( (char *)0, len = t-s) ) ;
  113.     (void) memcpy(sval->str, s, SIZE_T(len)) ;
  114.     s = t + mlen ;
  115.   }
  116.   temp_buff.ptr_buff[i++] = (PTR) new_STRING(s) ;
  117.  
  118.   return i ;
  119. }
  120.     
  121. /*  split(s, X, r)
  122.     split s into array X on r
  123.  
  124.     entry: sp[0] holds r
  125.            sp[-1] pts at X
  126.            sp[-2] holds s
  127. */
  128. CELL *bi_split(sp)
  129.   register CELL *sp ;
  130.   int cnt ;   /* the number of pieces */
  131.   CELL c_cnt ; /* CELL version of cnt */
  132.   ARRAY A ;
  133.   CELL  *cp ;
  134.  
  135.  
  136.   if ( sp->type < C_RE )  cast_for_split(sp) ;
  137.         /* can be C_RE, C_SPACE or C_SNULL */
  138.   sp -= 2 ;
  139.   if ( sp->type < C_STRING )  cast1_to_s(sp) ;
  140.  
  141.   if ( string(sp)->len == 0 ) /* nothing to split */
  142.   { free_STRING( string(sp) ) ;
  143.     sp->type = C_DOUBLE ; sp->dval = 0.0 ;
  144.     return sp ;
  145.   }
  146.  
  147.   switch ( (sp+2)->type )
  148.   {
  149.     case C_RE :
  150.         cnt = re_split(string(sp)->str, (sp+2)->ptr) ;
  151.         break ;
  152.  
  153.     case C_SPACE :
  154.         cnt = space_split(string(sp)->str, string(sp)->len) ;
  155.         break ;
  156.  
  157.     /* this case could be done by C_RE, but very slowly.
  158.        Since it is the common way to eliminate fields,
  159.        we'll treat the special case for speed */
  160.     case C_SNULL : /* split on empty string */
  161.         cnt = 1 ;
  162.         temp_buff.ptr_buff[0] = sp->ptr ;
  163.         string(sp)->ref_cnt++ ;
  164.         break ;
  165.  
  166.     default : bozo("bad splitting cell in bi_split") ;
  167.   }
  168.  
  169.   if ( cnt > MAX_SPLIT )
  170.     rt_overflow("maximum pieces from a split", MAX_SPLIT) ;
  171.  
  172.   /* now load the array */
  173.  
  174.   free_STRING( string(sp) ) ;
  175.  
  176.   c_cnt.type = sp->type = C_DOUBLE ;
  177.   c_cnt.dval = sp->dval = (double) cnt ;
  178.  
  179.   A = (ARRAY) (sp+1)->ptr  ;
  180.  
  181.   while ( cnt )
  182.   { 
  183.     cp = array_find( A, &c_cnt, CREATE) ;
  184.     cell_destroy(cp) ;
  185.     cp->ptr = temp_buff.ptr_buff[--cnt] ;
  186.     cp->type = C_MBSTRN ;
  187.  
  188.     c_cnt.dval -= 1.0 ;
  189.   }
  190.  
  191.   return sp ;
  192. }
  193.  
  194.